package it.webbased.site.client;

import it.webbased.site.client.ContactDataItem.ItemType;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.TextBoxBase;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class ContactPanel extends VerticalPanel {

	class FormItem {
		private TextBoxBase box;

		public FormItem(String name, ContactDataItem item) {
			if (item.getType().equals(ItemType.AREA)) {
				box = new TextArea();
				box.setPixelSize(200, 100);
			} else {
				box = new TextBox();
				box.setPixelSize(200, 30);
				box.addKeyPressHandler(new KeyPressHandler() {

					@Override
					public void onKeyPress(KeyPressEvent event) {
						switch (event.getCharCode()) {
						case '\r':
							ContactPanel.this.sendData();
							break;
						}
					}
				});
			}
			box.setName(name);

		}

		public Widget getBox() {
			return box;
		}

		public String getName() {
			return box.getName();
		}

		public String getText() {
			return box.getText();
		}

		public void resetValue() {
			box.setValue("");
		}
	}

	class SubmissionDialog extends DialogBox {
		private HTML text = new HTML();
		private String token;
		private Button close;

		public SubmissionDialog() {
			super();
			setAnimationEnabled(true);
			setText("Invio Dati");
			VerticalPanel p = new VerticalPanel();
			p.setSpacing(5);
			p.add(text);
			close = new Button("Chiudi", new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					SubmissionDialog.this.hide();
					ContactPanel.this.invia.setEnabled(true);
					Timer close = new Timer() {
						@Override
						public void run() {
							if (token != null)
								History.newItem(token);
						}
					};
					close.schedule(200);

				}
			});
			p.add(close);
			p.setCellHorizontalAlignment(close,
					HasHorizontalAlignment.ALIGN_RIGHT);

			add(p);
		}

		@Override
		public void center() {
			getWidget().setWidth("300px");
			super.center();
			close.setFocus(true);
		}

		public void setLabel(String text) {
			this.text.setHTML(text);
		}

		public void setRedirect(String token) {
			this.token = token;
		}

	}

	private static final boolean USE_WFS = false;

	private static final String WFS_RESOURCE = "http://";

	/**
	   * Make call to remote server.
	   */
	  public native static void getJson(int requestId, String url,
	      ContactPanel handler) /*-{
	   var callback = "callback" + requestId;

	   // [1] Create a script element.
	   var script = document.createElement("script");
	   script.setAttribute("src", url+callback);
	   script.setAttribute("type", "text/javascript");

	   // [2] Define the callback function on the window object.
	   window[callback] = function(jsonObj) {
	   // [3]
	     handler.@it.webbased.site.client.ContactPanel::handleJsonResponse(Ljava/lang/String;)(msg);
	     window[callback + "done"] = true;
	   }

	   // [4] JSON download has 1-second timeout.
	   setTimeout(function() {
	     if (!window[callback + "done"]) {
	       handler.@it.webbased.site.client.ContactPanel::handleJsonResponse(Ljava/lang/String;)(null);
	     }

	     // [5] Cleanup. Remove script and callback elements.
	     document.body.removeChild(script);
	     delete window[callback];
	     delete window[callback + "done"];
	   }, 1000);

	   // [6] Attach the script element to the document body.
	   document.body.appendChild(script);
	  }-*/;
	  
	final List<FormItem> items = new ArrayList<FormItem>();

	final SubmissionDialog dialog = new SubmissionDialog();
	final ContactData data = new ContactData();
	FlexTable table = new FlexTable();
	private String token;

	private Button invia;

	private int jsonRequestId = 0;

	public ContactPanel() {
		super();
		HTML html = new HTML();
		html.setHTML("<h2>Contatti</h2>");
		add(html);
		HorizontalPanel panel = new HorizontalPanel();
		panel.setSpacing(10);
		add(panel);
		panel.add(table);
		panel.add(new HTML("<p><b>CONSENSO LEGGE 675/96</b><br/>"
				+ "WebBased.it, in conformità con la Legge 675/96, "
				+ "dichiara che i dati vengono raccolti con la "
				+ "finalità di registrare l'utente e verranno "
				+ "trattati elettronicamente in conformità con "
				+ "le leggi vigenti. L'interessato gode dei diritti "
				+ "della legge 675/96. Premendo il pulsante per "
				+ "l'invio del form, si dà il consenso al "
				+ "trattamento dei dati personali.</p>"));
		table.setCellPadding(5);
		dialog.setAnimationEnabled(true);
		int i = 0;
		for (String k : data.getKeys()) {
			Label l = new Label();
			if (!data.get(k).isRequired())
				l.setText(k);
			else
				l.setText(k + "*");

			l.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
			table.setWidget(i, 0, l);
			table.getCellFormatter().setVerticalAlignment(i, 0,
					HasVerticalAlignment.ALIGN_TOP);
			items.add(new FormItem(k, data.get(k)));
			table.setWidget(i++, 1, items.get(items.size() - 1).getBox());
		}
		table.setWidget(i, 0, new Label("* Campo obbligatorio"));
		table.getFlexCellFormatter().setColSpan(i++, 0, 2);
		invia = new Button("Invia", new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				ContactPanel.this.sendData();
			}
		});
		table.setWidget(i, 1, invia);
		table.getCellFormatter().setHorizontalAlignment(i++, 1,
				HasHorizontalAlignment.ALIGN_RIGHT);

	}

	public void handleJsonResponse(String msg) {
		  if(msg==null) {
			  sendingFailure("Impossibile contattare il server remoto");
		  } else {
			  sendingSuccess(msg);
		  }
	  }

	private void sendData() {
		invia.setEnabled(false);
		StringBuffer formParams = new StringBuffer();
		for (FormItem key : items) {
			if (USE_WFS) {
				if (data.get(key.getName()).isRequired()) {
					formParams.append("req");
				}
				formParams.append(key.getName()).append("=").append(
						URL.encode(key.getText())).append("&");
			}
			data.setValue(key.getName(), key.getText());
		}

		String err = data.validate(false);
		if (!err.isEmpty()) {
			dialog.setLabel("Campi errati: <ul>" + err + "</ul>");
			dialog.setRedirect(null);
			dialog.center();
			return;
		}

		if (USE_WFS) {
			getJson(jsonRequestId++, WFS_RESOURCE+"?"+formParams, this);

		} else {
			ContactServiceAsync cs = GWT.create(ContactService.class);
			cs.addContact(data, new AsyncCallback<String>() {

				@Override
				public void onFailure(Throwable caught) {
					sendingFailure(caught.getMessage());
				}

				@Override
				public void onSuccess(String result) {
					sendingSuccess(result);
				}
			});
		}
	}
	private void sendingFailure(String message) {
		dialog.setLabel("Errore di invio: "+message);
		dialog.setRedirect(null);
		dialog.center();
	}
	  
	  private void sendingSuccess(String result) {
		dialog.setLabel(result);
		dialog.setRedirect(token);
		dialog.center();
		for (Iterator<FormItem> i = items.iterator(); i.hasNext();) {
			i.next().resetValue();
		}
	}
	  
	  public void setRedirect(String token) {
		this.token = token;
	}

}
